package gameengine.map;

import gameengine.map.unit.Unit;

public final class FireRange {

    private final transient Unit unit;
    private final transient Map map;

    private final transient int xSize, ySize;

    private final transient int xLocation, yLocation;

    private final transient boolean[] sectors;

    public FireRange(final int xCoordinate, final int yCoordinate, final Map mapParam) {
        this.map = mapParam;
        this.xLocation = xCoordinate;
        this.yLocation = yCoordinate;
        this.unit = this.map.getField(this.xLocation, this.yLocation).getUnit();
        this.xSize = this.map.getXSize();
        this.ySize = this.map.getYSize();

        this.sectors = new boolean[this.xSize * this.ySize];

        initBooleanField();
    }

    private void initBooleanField() {
        for (int i = 1; i <= this.map.getYSize(); i++) {
            for (int j = 1; j <= this.map.getXSize(); j++) {
                final long dis = getDistance(j, i);
                setField(j, i, dis >= this.unit.getMinFireRange() && dis <= this.unit.getMaxFireRange());
            }
        }
    }

    public boolean getField(final int xCoordinate, final int yCoordinate) {
        if (xCoordinate > this.xSize || yCoordinate > this.ySize || xCoordinate < 1 || yCoordinate < 1) {
            throw new IllegalArgumentException("Coordinates out of Range! " + xCoordinate + ":" + yCoordinate);
        }

        return this.sectors[((yCoordinate - 1) * this.xSize) + (xCoordinate - 1)];
    }

    private void setField(final int xCoordinate, final int yCoordinate, final boolean bool) {
        if (xCoordinate > this.xSize || yCoordinate > this.ySize || xCoordinate < 1 || yCoordinate < 1) {
            return;
        }

        this.sectors[((yCoordinate - 1) * this.xSize) + (xCoordinate - 1)] = bool;
    }

    private long getDistance(final int xCoordinate, final int yCoordinate) {
        final int xDistance = xCoordinate - this.xLocation;
        final int yDistance = yCoordinate - this.yLocation;

        return (int) Math.round(Math.sqrt(xDistance * xDistance + yDistance * yDistance));
    }
}
